package com.zgzg.shop.pay.base.utils;

import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.regex.Pattern;

public class TimeUtils {

    public static final ZoneId DEFAULT_TIMEZONE = ZoneId.of("Asia/Shanghai");

    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final DateTimeFormatter DATE_FORMATTER1 = DateTimeFormatter.ofPattern("yyyy-MM-d");
    private static final DateTimeFormatter DATE_FORMATTER2 = DateTimeFormatter.ofPattern("yyyy-M-d");
    private static final DateTimeFormatter DATE_FORMATTER3 = DateTimeFormatter.ofPattern("yyyy-M-dd");
    private static final DateTimeFormatter DATE_FORMATTER4 = DateTimeFormatter.ofPattern("yyyy/MM/dd");
    private static final DateTimeFormatter DATE_FORMATTER5 = DateTimeFormatter.ofPattern("yyyy/MM/d");
    private static final DateTimeFormatter DATE_FORMATTER6 = DateTimeFormatter.ofPattern("yyyy/M/d");
    private static final DateTimeFormatter DATE_FORMATTER7 = DateTimeFormatter.ofPattern("yyyy/M/dd");
    public static final DateTimeFormatter DATE_FORMATTER8 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    public static final DateTimeFormatter DATE_FORMATTER9 = DateTimeFormatter.ofPattern("yyyyMMdd");

    private static final Pattern dp = Pattern.compile("^\\d{4}-\\d{2}-\\d{2}$");
    private static final Pattern dp1 = Pattern.compile("^\\d{4}-\\d{2}-\\d{1}$");
    private static final Pattern dp2 = Pattern.compile("^\\d{4}-\\d{1}-\\d{1}$");
    private static final Pattern dp3 = Pattern.compile("^\\d{4}-\\d{1}-\\d{2}$");
    private static final Pattern dp4 = Pattern.compile("^\\d{4}/\\d{2}/\\d{2}$");
    private static final Pattern dp5 = Pattern.compile("^\\d{4}/\\d{2}/\\d{1}$");
    private static final Pattern dp6 = Pattern.compile("^\\d{4}/\\d{1}/\\d{1}$");
    private static final Pattern dp7 = Pattern.compile("^\\d{4}/\\d{1}/\\d{2}$");
    private static final Pattern dtp = Pattern.compile("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}$");
    private static final Pattern year = Pattern.compile("^\\d{4}");
    private static final Pattern timestamp = Pattern.compile("^[0-9]*$");


    public static String format(LocalDateTime localDateTime, DateTimeFormatter dateTimeFormatter) {
        return localDateTime.format(dateTimeFormatter);
    }

    public static boolean isTimestamp(String dateString) {
        if (timestamp.matcher(dateString).matches()) {
            return true;
        }
        return false;
    }

    public static boolean isMatch(String dateString) {
        if (dtp.matcher(dateString).matches()
                || dp.matcher(dateString).matches()
                || dp1.matcher(dateString).matches()
                || dp2.matcher(dateString).matches()
                || dp3.matcher(dateString).matches()
                || dp4.matcher(dateString).matches()
                || dp5.matcher(dateString).matches()
                || dp6.matcher(dateString).matches()
                || dp7.matcher(dateString).matches()
                || year.matcher(dateString).matches()) {
            return true;
        } else {
            return false;
        }
    }

    public static LocalDateTime parse(String dateString) {
        if (!StringUtils.hasText(dateString)) {
            return null;
        }
        if (dtp.matcher(dateString).matches()) {
            return LocalDateTime.parse(dateString, DATETIME_FORMATTER);
        } else if (dp.matcher(dateString).matches()) {
            LocalDate date = LocalDate.parse(dateString, DATE_FORMATTER);
            return LocalDateTime.of(date, LocalTime.of(0, 0, 0));
        } else if (dp1.matcher(dateString).matches()) {
            LocalDate date = LocalDate.parse(dateString, DATE_FORMATTER1);
            return LocalDateTime.of(date, LocalTime.of(0, 0, 0));
        } else if (dp2.matcher(dateString).matches()) {
            LocalDate date = LocalDate.parse(dateString, DATE_FORMATTER2);
            return LocalDateTime.of(date, LocalTime.of(0, 0, 0));
        } else if (dp3.matcher(dateString).matches()) {
            LocalDate date = LocalDate.parse(dateString, DATE_FORMATTER3);
            return LocalDateTime.of(date, LocalTime.of(0, 0, 0));
        } else if (dp4.matcher(dateString).matches()) {
            LocalDate date = LocalDate.parse(dateString, DATE_FORMATTER4);
            return LocalDateTime.of(date, LocalTime.of(0, 0, 0));
        } else if (dp5.matcher(dateString).matches()) {
            LocalDate date = LocalDate.parse(dateString, DATE_FORMATTER5);
            return LocalDateTime.of(date, LocalTime.of(0, 0, 0));
        } else if (dp6.matcher(dateString).matches()) {
            LocalDate date = LocalDate.parse(dateString, DATE_FORMATTER6);
            return LocalDateTime.of(date, LocalTime.of(0, 0, 0));
        } else if (dp7.matcher(dateString).matches()) {
            LocalDate date = LocalDate.parse(dateString, DATE_FORMATTER7);
            return LocalDateTime.of(date, LocalTime.of(0, 0, 0));
        } else if (year.matcher(dateString).matches()) {
            LocalDate date = LocalDate.parse(dateString + "-01-01", DATE_FORMATTER);
            return LocalDateTime.of(date, LocalTime.of(0, 0, 0));
        } else {
            throw new RuntimeException("Malformed date string: " + dateString);
        }
    }

    public static LocalDate parseDate(String dateString) {
        if (!StringUtils.hasText(dateString)) {
            return null;
        }
        if (dp.matcher(dateString).matches()) {
            return LocalDate.parse(dateString, DATE_FORMATTER);
        } else {
            throw new RuntimeException("Malformed date string: " + dateString);
        }
    }

    public static Long getTimestampFromDateStart(String dateStart) {
        if (dateStart != null && dp.matcher(dateStart).matches()) {
            LocalDate date = LocalDate.parse(dateStart, DATE_FORMATTER);
            LocalDateTime dayStart = LocalDateTime.of(date, LocalTime.of(0, 0, 0));
            return getTimestamp(dayStart);
        }
        return null;
    }

    public static Long getTimestampFromDateEnd(String dateEnd) {
        if (dateEnd != null && dp.matcher(dateEnd).matches()) {
            LocalDate date = LocalDate.parse(dateEnd, DATE_FORMATTER);
            LocalDateTime dayEnd = LocalDateTime.of(date, LocalTime.of(23, 59, 59));
            return getTimestamp(dayEnd);
        }
        return null;
    }

    public static LocalDateTime getNow() {
        return LocalDateTime.now();
    }

    public static LocalDateTime getTodayStart() {
        LocalDateTime now = LocalDateTime.now();
        return LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 0, 0, 0);
    }

    public static LocalDateTime getDayStart(LocalDateTime dateTime) {
        if (dateTime != null) {
            return LocalDateTime.of(dateTime.getYear(), dateTime.getMonth(), dateTime.getDayOfMonth(), 0, 0, 0);
        }
        return null;
    }

    public static LocalDateTime getTodayEnd() {
        LocalDateTime now = LocalDateTime.now();
        return LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 23, 59, 59);
    }

    public static LocalDateTime getDayEnd(LocalDateTime dateTime) {
        if (dateTime != null) {
            return LocalDateTime.of(dateTime.getYear(), dateTime.getMonth(), dateTime.getDayOfMonth(), 23, 59, 59);
        }
        return null;
    }

    public static long getTimestamp(LocalDateTime localDateTime) {
        Date date = Date.from(localDateTime.atZone(DEFAULT_TIMEZONE).toInstant());
        return date.getTime();
    }

    public static long getTimestamp(String dateString, DateTimeFormatter dateTimeFormatter) {
        LocalDateTime localDateTime = LocalDateTime.parse(dateString, dateTimeFormatter);
        return getTimestamp(localDateTime);
    }

    public static LocalDateTime getLocalDateTime(Long timestamp) {
        if (timestamp == null) {
            return null;
        }
        Date date = new Date(timestamp);
        return LocalDateTime.ofInstant(date.toInstant(), TimeUtils.DEFAULT_TIMEZONE);
    }

    //Date转LocalDateTime
    public static LocalDateTime parseDateToLocalDateTime(Date date) {
        if (date == null) {
            return null;
        }
        return LocalDateTime.ofInstant(date.toInstant(), TimeUtils.DEFAULT_TIMEZONE);
    }

    //Date转yyyy-MM-dd
    public static String parseDateToDateString(Date date) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        return formatter.format(date);
    }

    public static long getMillisBetween(LocalDateTime beginTime, LocalDateTime endTime) {
        return Duration.between(beginTime, endTime).toMillis();
    }

    public static boolean checkTimeBetween(LocalDateTime beginTime, LocalDateTime endTime, int minute) {
        return Duration.between(beginTime, endTime).toMinutes() > minute;
    }

    public static void main(String[] args) {
        String s = "2020-11-1";
        System.out.println(parse(s));
    }

    public static LocalDateTime parseDateTime2LocalDateTime(String dateTimeString) {
        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        return LocalDateTime.parse(dateTimeString, formatter);
    }
}
